package com.intelligent.mts.da.handler;

import com.intelligent.mts.core.utils.AppConst;
import com.intelligent.mts.da.codec.HttpXmlRequestDecoder;
import com.intelligent.mts.da.codec.HttpXmlResponseEncoder;
import com.intelligent.mts.da.server.HttpXmlServerHandler;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.http.*;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.stream.Collector;

/**
 * Created by Garen.Pang on 2016/9/3.
 */
public class ProtocolAdapterHandler extends ByteToMessageDecoder {

    public static Logger logger = LoggerFactory.getLogger(ProtocolAdapterHandler.class);

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        super.channelReadComplete(ctx);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> list) throws Exception {


        StringBuffer resulttype = new StringBuffer();
        for (int i = 0; i < byteBuf.readableBytes(); i++) {
            resulttype.append( (char) byteBuf.getByte(i));
        }

        StringBuffer sb = new StringBuffer();

        char[] result = new char[4];
        for (int i = 0; i < 4; i++) {
            result[i] = (char) byteBuf.getByte(i);
            sb.append(result[i]);
        }

        String first4 = sb.toString();

        ChannelPipeline p = ctx.pipeline();
        this.clearPipeline(p);
        this.clearTCPPipeline(p);
        this.clearHTTPPipeline(p);
        if ((first4.equals(AppConst.START_VALIDATE_REQ) || first4.equals(AppConst.START_STATUS_REQ) ||
                first4.equals(AppConst.START_OFFLINE_REQ) || first4.equals(AppConst.START_DATA_REQ)|| first4.equals(AppConst.START_HEARTBEAT)) && resulttype.toString().trim().endsWith("#")){
            p.addLast("StringDecoder", new StringDecoder());
            p.addLast("StringEncoder", new StringEncoder());
            p.addLast("AdapterHandler", new AdapterHandler());
            p.addLast("TcpOutHandler",new TcpOutHandler());

            byteBuf.retain();
            ctx.fireChannelRead(byteBuf);
            byteBuf.clear();
        }else {
            p.addLast("http-decoder", new HttpRequestDecoder());
            p.addLast("http-aggregator", new HttpObjectAggregator(65536));
            p.addLast("xml-decoder", new HttpXmlRequestDecoder(Object.class, true));
            p.addLast("http-encoder", new HttpResponseEncoder());
            p.addLast("xml-encoder", new HttpXmlResponseEncoder());
            p.addLast("xmlServerHandler", new HttpXmlServerHandler());
            p.addLast("HttpOutHandler",new HttpOutHandler());
            byteBuf.retain();
            ctx.fireChannelRead(byteBuf);
            byteBuf.clear();
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        logger.warn("Unexpected exception from com.intelligent.mts.da.handler " + cause);
        ctx.fireExceptionCaught(cause);
    }

    private void clearTCPPipeline(ChannelPipeline p)
    {
        if (p.get("AdapterHandler") != null) {
            p.remove("AdapterHandler");
        }
        if (p.get("StringDecoder") != null) {
            p.remove("StringDecoder");
        }
        if (p.get("StringEncoder") != null) {
            p.remove("StringEncoder");
        }
        if (p.get("TcpOutHandler") != null){
            p.remove("TcpOutHandler");
        }
    }
    private void clearPipeline(ChannelPipeline p)
    {
        if (p.get("validateHandler") != null) {
            p.remove("validateHandler");
        }
        if (p.get("updateStatusHandler") != null) {
            p.remove("updateStatusHandler");
        }
        if (p.get("saveDataHandler") != null) {
            p.remove("saveDataHandler");
        }
        if (p.get("saveOfflineDataHandler") != null) {
            p.remove("saveOfflineDataHandler");
        }

        if (p.get("heartbeatHandler") != null) {
            p.remove("heartbeatHandler");
        }
    }
    private void clearHTTPPipeline(ChannelPipeline p)
    {
        if (p.get("http-decoder") != null) {
            p.remove("http-decoder");
        }
        if (p.get("http-aggregator") != null) {
            p.remove("http-aggregator");
        }
        if (p.get("xml-decoder") != null) {
            p.remove("xml-decoder");
        }
        if (p.get("http-encoder") != null) {
            p.remove("http-encoder");
        }

        if (p.get("xml-encoder") != null) {
            p.remove("xml-encoder");
        }

        if (p.get("xmlServerHandler") != null) {
            p.remove("xmlServerHandler");
        }

        if (p.get("HttpOutHandler") != null){
            p.remove("HttpOutHandler");
        }
    }
}
